﻿using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Newtonsoft.Json;
using OpenCvSharp;
using OpenCvSharp.WpfExtensions;
using PLCSharp.CoreModel.Common;
using PLCSharp.CoreModel.Tools;
using PLCSharp.CoreModel.UserControls;
using PLCSharp.Views.Homepage.TableControl;
using Prism.Mvvm;
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Brush = System.Windows.Media.Brush;
using FontFamily = System.Windows.Media.FontFamily;


namespace PLCSharp.Views.Homepage
{
    public class CustomControl : BindableBase
    {
        [Key]
        public Guid ID { get; set; } = Guid.NewGuid();
        public Guid RecipeID { get; set; }
        private string _Name;
        /// <summary>
        /// Comment
        /// </summary>
        public string Name
        {
            get { return _Name; }
            set
            {
                if (_Name != value)
                {
                    Prompt = "已修改，请保存";
                }
                SetProperty(ref _Name, value);
            }
        }

        private ControlType _Type;
        /// <summary>
        /// Comment
        /// </summary>
        public ControlType Type
        {
            get { return _Type; }
            set { SetProperty(ref _Type, value); }
        }

        private string _Prompt;
        [NotMapped]
        /// <summary>
        /// 提示
        /// </summary>
        public string Prompt
        {
            get { return _Prompt; }
            set { SetProperty(ref _Prompt, value); }
        }
        private int _Row;
        /// <summary>
        /// Comment
        /// </summary>
        public int Row
        {
            get { return _Row; }
            set { SetProperty(ref _Row, value); }
        }

        private int _Column;
        /// <summary>
        /// Comment
        /// </summary>
        public int Column
        {
            get { return _Column; }
            set { SetProperty(ref _Column, value); }
        }

        private int _RowSpan;
        /// <summary>
        /// Comment
        /// </summary>
        public int RowSpan
        {
            get { return _RowSpan; }
            set { SetProperty(ref _RowSpan, value); }
        }

        private int _ColumnSpan;
        /// <summary>
        /// Comment
        /// </summary>
        public int ColumnSpan
        {
            get { return _ColumnSpan; }
            set { SetProperty(ref _ColumnSpan, value); }
        }
        private string _Comment;
        /// <summary>
        /// 备注
        /// </summary>
        public string Comment

        {
            get { return _Comment; }
            set
            {
                if (_Comment != value)
                {
                    Prompt = "已修改，请保存";
                }
                SetProperty(ref _Comment, value);
            }
        }
        #region Params
        [Column("Params")]


        public string SerializedParams
        {
            get => JsonConvert.SerializeObject(Params); // 自动序列化
            set => Params = JsonConvert.DeserializeObject<ControlParams>(value); // 自动反序列化

        }
        private ControlParams _Params;
        [JsonIgnore]
        [NotMapped]
        /// <summary>
        /// Comment
        /// </summary>
        public ControlParams Params
        {
            get
            {
                _Params ??= new ControlParams();

                return _Params;
            }
            set
            {
                SetProperty(ref _Params, value);

            }
        }
        #endregion
        private ObservableCollection<RangeValue> _RangeValues = [];
        [NotMapped]
        /// <summary>
        /// Comment
        /// </summary>
        public ObservableCollection<RangeValue> RangeValues
        {
            get { return _RangeValues; }
            set { if (value != null) SetProperty(ref _RangeValues, value); }
        }

        [Column("RangeValues")]


        public string SerializedRangeValues
        {
            get => JsonConvert.SerializeObject(RangeValues); // 自动序列化
            set => RangeValues = JsonConvert.DeserializeObject<ObservableCollection<RangeValue>>(value); // 自动反序列化

        }
        public void SetCellState(int index, CellState cellState)
        {
            var cell = Params.CellInfos.Where(c => c.Index == index).FirstOrDefault();
            if (cell != null)
            {
                cell.State = cellState;
            }
            else
            {
                throw new Exception($"未找到索引{index}的单元格");
            }

        }
        private WriteableBitmap _ImgSrc;
        [NotMapped]
        public WriteableBitmap ImgSrc
        {
            get { return _ImgSrc; }
            set { SetProperty(ref _ImgSrc, value); }
        }
        public void ShowMat(Mat _ShowMat)
        {
            if (_ShowMat == null) return;
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                if (_ImgSrc != null
                && _ShowMat.Width == _ImgSrc.PixelWidth
                && _ShowMat.Height == _ImgSrc.PixelHeight
                && _ShowMat.Channels() == _ImgSrc.Format.BitsPerPixel / 8
                    )
                {
                    WriteableBitmapConverter.ToWriteableBitmap(_ShowMat, _ImgSrc);

                }
                else
                {
                    ImgSrc = WriteableBitmapConverter.ToWriteableBitmap(_ShowMat);
                }
            }));

        }
        /// <summary>
        /// 显示圆
        /// </summary>
        /// <param name="centerRow">中心点X</param>
        /// <param name="centerY">中心点Y</param>
        /// <param name="radiusRow">半径X</param>
        /// <param name="radiusColumn">半径Y</param>
        /// <param name="color">颜色</param>
        /// <param name="thickness">线径</param>
        public void ShowEllipse(double centerRow, double centerColumn, double radiusRow, double radiusColumn, Brush color, double thickness = 3)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
           {
               Path path = new()
               {
                   StrokeThickness = thickness,
                   Stroke = color
               };
               var g = new EllipseGeometry
               {
                   Center = new() { X = centerRow, Y = centerColumn },
                   RadiusX = radiusRow,
                   RadiusY = radiusColumn
               };
               path.Data = g;
               var ui = UIElement as ImageEdit;
               ui.Draw(path);
           }));

        }
        /// <summary>
        /// 显示线段
        /// </summary>
        /// <param name="fromRow"></param>
        /// <param name="fromColumn"></param>
        /// <param name="toRow"></param>
        /// <param name="toColumn"></param>
        /// <param name="thickness"></param>
        /// <param name="color"></param>
        /// <param name="thickness"></param>
        public void ShowLine(double fromRow, double fromColumn, double toRow, double toColumn, Brush color, double thickness = 3)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                Path path = new()
                {
                    StrokeThickness = thickness,
                    Stroke = color//设置Path基础属性
                };
                var g = new LineGeometry
                {
                    StartPoint = new() { X = fromRow, Y = fromColumn },
                    EndPoint = new() { X = toRow, Y = toColumn },

                };
                path.Data = g;
                var ui = UIElement as ImageEdit;
                ui.Draw(path);
            }));

        }
        private static XPoint[] GetArrowPoints(XPoint end, XPoint start, float size)
        {
            XPoint[] points = new XPoint[2];

            // 计算箭头的角度
            double angle = Math.Atan2(end.Y - start.Y, end.X - start.X);

            // 计算箭头顶点的位置


            // 计算箭头左侧端点位置
            points[0] = new XPoint
            {
                X = (float)(end.X - size * Math.Cos(angle + Math.PI / 8)),
                Y = (float)(end.Y - size * Math.Sin(angle + Math.PI / 8))
            };

            // 计算箭头右侧端点位置
            points[1] = new XPoint
            {
                X = (float)(end.X - size * Math.Cos(angle - Math.PI / 8)),
                Y = (float)(end.Y - size * Math.Sin(angle - Math.PI / 8))
            };

            return points;
        }
        public void ShowArrowLine(string name,double fromRow, double fromColumn, double toRow, double toColumn, Brush color, double thickness = 3)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                Path path = new()
                {
                    StrokeThickness = thickness,
                    Stroke = color,
                    Tag = name
                };
                var g = new LineGeometry
                {
                    StartPoint = new() { X = fromColumn, Y = fromRow },
                    EndPoint = new() { X = toColumn, Y = toRow },

                };
                path.Data = g;
                var ui = UIElement as ImageEdit;
                ui.Draw(path);

                var headlen = 30;//箭头线的长度

                var startPoint = new XPoint() { X = fromColumn, Y = fromRow };
                var endPoint = new XPoint() { X = toColumn, Y = toRow };

                XPoint[] points = GetArrowPoints(endPoint, startPoint, headlen);
 
                var line2 = new Line
                {
                    Stroke = color,
                    StrokeThickness = thickness,
                    X1 = points[1].X,
                    Y1 = points[1].Y,
                    X2 = toColumn,
                    Y2 = toRow,
                    Tag = name
                };

                ui.Draw(line2);


                var line3 = new Line
                {
                    Stroke = color,
                    StrokeThickness = thickness,
                    X1 = points[0].X,
                    Y1 = points[0].Y,
                    X2 = toColumn,
                    Y2 = toRow,
                    Tag = name
                };

                ui.Draw(line3);

            }));

        }
        public void ShowCross(int pointRow, int pointColumn, int width, int height, Brush color, double thickness = 3)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {

                var g1 = new LineGeometry
                {
                    StartPoint = new() { X = pointRow - width / 2, Y = pointColumn },
                    EndPoint = new() { X = pointRow + width / 2, Y = pointColumn },

                };
                var g2 = new LineGeometry
                {
                    StartPoint = new() { X = pointRow, Y = pointColumn - height / 2 },
                    EndPoint = new() { X = pointRow, Y = pointColumn + height / 2 },

                };
                var ui = UIElement as ImageEdit;
                Path path1 = new()
                {
                    StrokeThickness = thickness,
                    Stroke = color,
                    Data = g1
                };
                ui.Draw(path1);

                Path path2 = new()
                {
                    StrokeThickness = thickness,
                    Stroke = color
                };
                path2.Data = g2;
                ui.Draw(path2);
            }));

        }
        public void ShowRectangle(int pointRow, int pointColumn, int width, int height, Brush color, double thickness = 3)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {

                var g1 = new RectangleGeometry
                {

                    RadiusX = pointRow - width / 2,
                    RadiusY = pointColumn

                };


                Path path1 = new()
                {
                    StrokeThickness = thickness,
                    Stroke = color
                };
                path1.Data = g1;
                var ui = UIElement as ImageEdit;
                ui.Draw(path1);


            }));

        }
        public void ShowArc(XPoint startPoint, XPoint middlePoint, XPoint endPoint, Brush color, double thickness = 3)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                PathGeometry geometry = new();
                PathFigure figure = new()
                {
                    StartPoint = new() { X = startPoint.X, Y = startPoint.Y }
                };
                figure.Segments.Add(new ArcSegment() {
 
                Point =     new() { X =endPoint .X, Y =endPoint .Y },
                Size  =    new() { Width = middlePoint.X, Height =middlePoint .Y },  
                
                });
                geometry.Figures.Add(figure);

                Path path1 = new()
                {
                    StrokeThickness = thickness,
                    Stroke = color
                };
                path1.Data = geometry;
                var ui = UIElement as ImageEdit;
                ui.Draw(path1);
            }));


        }
        public void ShowText(int pointRow, int pointColumn, string text, double fontSize, Brush color, double thickness = 3)
        {
            System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
            {
                TextBlock textBlock = new()
                {
                    Text = text,
                    FontSize = fontSize,
                    FontFamily = new FontFamily("Arial"),
                    Foreground = color
                };

                var ui = UIElement as ImageEdit;
                ui.Draw(textBlock, pointRow, pointColumn);
            }));

        }

        public void SetCellState(int row, int column, CellState cellState)
        {

            var cell = Params.CellInfos.Where(c => c.Row == row && c.Column == column).FirstOrDefault();
            if (cell != null)
            {
                cell.State = cellState;
            }
            else
            {
                throw new Exception($"未找到行{row}列{column}的单元格");
            }

        }
        [NotMapped]
        public UIElement UIElement { get; set; }
        public class ControlParams : BindableBase
        {
            private int _Rows;
            /// <summary>
            /// Comment
            /// </summary>
            public int Rows
            {
                get { return _Rows; }
                set { SetProperty(ref _Rows, value); }
            }
            private int _Columns;
            /// <summary>
            /// Comment
            /// </summary>
            public int Columns
            {
                get { return _Columns; }
                set { SetProperty(ref _Columns, value); }
            }

            private int _Layout;
            /// <summary>
            /// 布局方法  0-排列正序 1-排列倒序  2-列排正序 3-列排倒序   
            /// </summary>
            public int Layout
            {
                get { return _Layout; }
                set { SetProperty(ref _Layout, value); }
            }

            private ObservableCollection<CellInfo> _CellInfos = [];
            /// <summary>
            /// 
            /// </summary>
            public ObservableCollection<CellInfo> CellInfos
            {
                get { return _CellInfos; }
                set
                {
                    if (value != null)
                        SetProperty(ref _CellInfos, value);
                }
            }

        }
    }
    public enum ControlType
    {
        Image,
        State,
        RangeValueTalbe,

    }
}
